package com.cx.utils;

import org.apache.commons.lang3.StringUtils;

import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQuery;
import java.io.Closeable;
import java.io.IOException;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by 舒建辉.
 * Date time 2019/3/12 21:57
 */
public interface CacheConsts {

    /**
     * 缓存模式(ASYNC|ASYNC_PIPELINE|REACTIVE|REACTIVE_PIPELINE)
     */
     String ASYNC = "ASYNC";
     String ASYNC_PIPELINE = "ASYNC_PIPELINE";
     String REACTIVE = "REACTIVE";
     String REACTIVE_PIPELINE = "REACTIVE_PIPELINE";

    /**
     * 缓存keyspace分隔符
     */
     String SP = ":";

    /**
     * 重试次数
     */
     int RETRY_TIMES = 5;

    /**
     * 不设重试次数
     */
     int NO_RETRY_TIMES = 0;

    /**
     * 默认buffer大小
     */
     int DEFAULT_BUFFER_SIZE = 1234;

    /**
     * 返回值OK
     */
     String OK = "OK";

    /**
     * 返回值NIL
     */
     String NIL = "nil";

    /**
     * 默认异步结果超时时间（毫秒）
     */
    Duration ASYNC_RESULT_TIMEOUT = Duration.ofMillis(1000);

    /**
     * 默认异步结果超时后补偿时间（毫秒）
     */
    long ADD_ASYNC_RESULT_MILLIS = 5L;

    /**
     * 序列化类型(KRYO|FST|PROTOSTUFF|FASTJSON)
     */
     String SERIALIZE_TYPE_KRYO = "KRYO";
     String SERIALIZE_TYPE_FST = "FST";
     String SERIALIZE_TYPE_PROTOSTUFF = "PROTOSTUFF";
     String SERIALIZE_TYPE_FASTJSON = "FASTJSON";

    /**
     * sql分析取出表名加入待删除的key列表（增删改时的要删除已缓存的key），将缓存起来
     */
    static Map<String, String> delingCacheKeys(String query){

        final Map<String, String> delingCacheKeys = new HashMap(2);

        final StringBuffer sb = new StringBuffer("(?i)(?<=(?:from|into|update|join)\\s{1,1000}");
        for(int i = 0; i < 4; i++) {
            sb.append("(?:\\w{1,1000}(?:\\s{0,1000},\\s{0,1000})?)?"); // 重复这里, 可以多个from后面的表
        }
        sb.append(")(\\w+)");

        final Matcher m = Pattern.compile(sb.toString()).matcher(query.toLowerCase());
        while (m.find()) {
            final String table = m.group();
            final String delingCachePartKey = SerializeAdapter.lettuceProperties().cacheLevel2Pre() + table + ":finds:*";
            if(!delingCacheKeys.containsValue(table) && StringUtils.isNotEmpty(delingCachePartKey)) {
                delingCacheKeys.put(table, delingCachePartKey);
            }
        }

        if(delingCacheKeys.size() <= 1){
            delingCacheKeys.clear();
        }

        return delingCacheKeys;
    }

    /**
     * 批量操作
     */
    static Map<String, String> batchDelingCacheKeys(NamedQuery[] namedQueries){
        final Map<String, String> batchDelingCacheKeys = new HashMap(10);
        Arrays.stream(namedQueries).forEach(namedQuery -> {
            batchDelingCacheKeys.putAll(delingCacheKeys(namedQuery.query()));
        });

        return batchDelingCacheKeys;
    }

    /**
     * 批量操作
     */
    static Map<String, String> batchDelingCacheKeys(NamedNativeQuery[] namedNativeQueries){
        final Map<String, String> batchDelingCacheKeys = new HashMap(10);
        Arrays.stream(namedNativeQueries).forEach(namedNativeQuery -> {
            batchDelingCacheKeys.putAll(delingCacheKeys(namedNativeQuery.query()));
        });

        return batchDelingCacheKeys;
    }

    static void close(Closeable closeable){
        if(null != closeable){
            try {
                closeable.close();
            } catch (IOException e) {
                // ignore close exception
            }
        }
    }

    static void close(AutoCloseable autoCloseable){
        if (autoCloseable != null) {
            try {
                autoCloseable.close();
            } catch (Exception e) {
                // ignore auto close exception
            }
        }
    }
}